package com.ewins.weatherdataclient.downloadservice;

import com.ewins.weatherdataclient.common.Constant;
import com.ewins.weatherdataclient.downloadmodule.*;
import com.ewins.weatherdataclient.https.HttpsDefault;
import com.ewins.weatherdatautils.bean.*;
import com.ewins.weatherdatautils.utils.Configuration;
import com.ewins.weatherdatautils.utils.SqliteAccess;
import com.ewins.weatherdatautils.utils.Utils;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import org.apache.log4j.Logger;
import org.joda.time.DateTime;

import javax.net.ssl.HttpsURLConnection;
import java.io.File;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.*;
import java.util.Date;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;

/**
 * 文件下载，开启文件下载下载模块线程
 */
public class FileDownloadMonitorHttp implements Runnable{
    private static final String path = System.getProperty("user.dir");
    String dbFileName = Configuration.GetValueByKey(path + File.separator + "config" + File.separator + "config.properties", "DBFILENAME");
    DownLoadFileInfo fileInfo;
    final ThreadLocal<SiteInfoBean> bean = new ThreadLocal<SiteInfoBean>();
    SiteFileFetchHttp fileFetch;

    SimpleDateFormat dfs = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    boolean isFirst=true;
    Date dateStr;
    Date dateEnd;

    //EventBus eventBus = new EventBus();
    boolean needStop = false;
    EventBus eventBus;
    Logger log=Logger.getLogger(FileDownloadMonitorHttp.class);

    public DownLoadFileInfo getFileInfo() {
        return fileInfo;
    }

    public void setFileInfo(DownLoadFileInfo fileInfo) {
        this.fileInfo = fileInfo;
    }

//    public FileDownloadMonitor()
//    {
//        eventBus.register(this);
//    }

    public FileDownloadMonitorHttp(EventBus eb)
    {
        this.eventBus=eb;
        eventBus.register(this);
    }

    @Subscribe
    public void onMessage(DownloadStateBean ds) {
        // TODO Auto-generated method stub
        if (ds.getIsDownload().equals("T")) {
                if (ds.isContinue()) {
                    fileInfo.setState(DownLoadState.Pause);
                    fileInfo.setErrorDesc(ds.getFileError());
                    needStop = true;
                } else {
                    fileInfo.setState(DownLoadState.Error);
                    fileInfo.setErrorDesc(ds.getFileError());
                    needStop = true;
                }
        }
        else {
            fileInfo.setErrorDesc(ds.getFileError());
        }
        if (!needStop) {
            updateDownLoadProgess();
        }
    }

    /**
     * 更新下载进度
     */
    private void updateDownLoadProgess()
    {
        double loadedLength = calculatorLoadLengrh();
        if(loadedLength >= 0) {
            DecimalFormat df = new DecimalFormat("0.00");
            String downloadPercent = df.format(loadedLength) + "%";
            //SysLogger.info(fileInfo.getFileName() + "文件已经下载：" + downloadPercent);
            fileInfo.setCreatedTime(fileInfo.getCreatedTime());     //开始时间
            if (loadedLength >= 100) {
                fileInfo.setState(DownLoadState.Finished);
                fileInfo.setLoadProgress("100.00%");
//                fileFetch.deleteInfoFile(bean.get());
                needStop = true;
                if(!searchLocalFileList(fileInfo.getFileName(),fileInfo.getCreatedTimeDesc())){
                    insertFile(fileInfo);
                    insertHistoryFile(fileInfo);
                    log.info(fileInfo.getFileName() + "文件已经下载完成：" + downloadPercent);
                }
            } else if (loadedLength >= 0) {
                //needStop = false;
                fileInfo.setLoadProgress(downloadPercent);
                fileInfo.setErrorDesc("");
            }
        }
    }

    public void run() {
        log.info("开始下载文件：" + fileInfo.getFileName());
        if( getFileLengthUrl(fileInfo.getUrl())<0){
            fileInfo.setState(DownLoadState.Pause);
        }else{
            fileInfo.setState(DownLoadState.Loading);
        }
        try {
            bean.set(new SiteInfoBean(fileInfo.getUrl(), fileInfo.getLocalFilePath(), fileInfo.getFileName(), Constant.FileDownloadThreadCount,fileInfo.getCreatedTime(),fileInfo.getFilePriority(),fileInfo.getStartDownLoadTime(),fileInfo.getCategoryName()));
            checkFilePath(bean.get());
            fileFetch = new SiteFileFetchHttp(bean.get(), eventBus);
            fileFetch.start();

            while (true) {
                if(needStop){
                    fileFetch.siteStop();
                    break;
                }

                //需要强制暂停下载
                if (DownLoadState.Pause.equals(fileInfo.getState())) {
                    needStop = true;
                    fileFetch.siteStop();
                    break;
                }
                updateDownLoadProgess();

                //线程超时处理
                if(isFirst){
                    dateStr =new Date();
                    dateEnd=new Date();
                    this.isFirst=false;
                }else{
                    dateEnd= new Date();
                }
                long outTime = (dateEnd.getTime() - dateStr.getTime())/1000;   //单位;秒
                if(outTime>30*60){
                    fileInfo.setState(DownLoadState.Error);
                    fileInfo.setErrorDesc("下载失败");
                    needStop = true;
                    fileFetch.siteStop();
                    Utils.deleteRemoteFile(bean.get(), ".tmp");
                    Utils.deleteRemoteFile(bean.get(), ".info");
                    Thread.interrupted();
                    log.info(fileInfo.getFileName() + "文件已经下载失败");
                    break;
                }

                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    log.error(e);
                }
            }
        }catch (NullPointerException e){
            log.error(e.getMessage());   //文件下载异常处理
        }
        catch (Exception ex) {
            log.error(ex);
            ex.printStackTrace();
            //fileInfo.setState(DownLoadState.Error);
        }
    }

    long fileLength = -1;
    /**
     * 计算已下载长度
     */
    private double calculatorLoadLengrh() {
        try {
            long length = getFileLength(bean.get().getSFilePath() + File.separator + bean.get().getSFileName()+".tmp");        //local file length
            if (fileLength < 0) {
                fileLength = getFileLengthUrl(fileInfo.getUrl());    //source file length
            }
            if (fileLength < 0) return -1;
            double num = ((double) length / (double) fileLength) * 100;
            return num;
        } catch (Exception e) {
            log.error(e);
        }
        return -1;
    }

    //计算本地文件大小
    public static long getFileLength(String path){
        File file= new File(path);
        File finishedf= new File(path.substring(0,path.length()-4));
        //文件在完成下载后会删掉.tmp的临时文件名
        if (file.exists() && file.isFile()){
            return  file.length();
        }
        else if(finishedf.exists() && finishedf.isFile()){
            return finishedf.length();
        }
        else{
            return 0;
        }
    }

    public static void checkFilePath(SiteInfoBean bean) {
        File filepath = new File(bean.getSFilePath());

        if (!filepath.getParentFile().exists()) {
            filepath.getParentFile().mkdirs();
        }
        if (!filepath.exists() && !filepath.isDirectory()) {
            filepath.mkdir();
        }
    }

    /**
     * 下载文件改变事件
     */
    FileLoadChangedInfo onChangedInfo;

    public FileLoadChangedInfo getOnChangedInfo() {
        return onChangedInfo;
    }

    public void setOnChangedInfo(FileLoadChangedInfo onChangedInfo) {
        this.onChangedInfo = onChangedInfo;
    }

    private long getFileLengthUrl(String url) {
        long fileLength = -1;
        HttpURLConnection urlConnection = null;
        try {
            //进行一次文件连接
            URL resourceURL = new URL(url);
            urlConnection = (HttpURLConnection) resourceURL.openConnection();
            //urlConnection.setSSLSocketFactory(HttpsDefault.getSSLSocketFactory());
            urlConnection.setConnectTimeout(Constant.HttpConnectTimeout);
            urlConnection.setReadTimeout(Constant.HttpReadTimeout);
            urlConnection.setRequestProperty("User-Agent", "NetFox");
            String sHeader;
            for (int i = 1; ; i++) {
                sHeader = urlConnection.getHeaderFieldKey(i);
                if (sHeader != null) {
                    if (sHeader.equals("Content-Length")) {
                        fileLength = Long.parseLong(urlConnection.getHeaderField(sHeader));
                        break;
                    }
                } else
                    break;
            }
        } catch (Exception e) {
            log.error(e);
        } finally {
            try {
                if (urlConnection != null)
                    urlConnection.disconnect();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return fileLength;
    }


    /**
     * 将已下载的文件插入数据库
     * @throws Exception
     */
    public synchronized void insertFile(DownLoadFileInfo fileInfo){
        try {
            Class.forName("org.sqlite.JDBC");
            Connection conn = DriverManager.getConnection("jdbc:sqlite:" + dbFileName);
            conn.setAutoCommit(true);

            String sql = "insert INTO currentfile VALUES (?,?,?,?,?,?) ";

            PreparedStatement stat = conn.prepareStatement(sql);

            stat.setString(1, fileInfo.getFileName());
            stat.setInt(2, fileInfo.getFilePriority());
            stat.setString(3, fileInfo.getUrl());
            stat.setString(4, fileInfo.getCreatedTime().toString("yyyy-MM-dd HH:mm:ss"));
            stat.setString(5, fileInfo.getCategoryName());
            stat.setString(6, fileInfo.getStartDownLoadTime().toString("yyyy-MM-dd HH:mm:ss"));

            stat.executeUpdate();
            stat.close();
            conn.close();

        }catch (Exception e){
            log.error(e.getMessage());
        }
    }

    public synchronized void insertHistoryFile(DownLoadFileInfo fileInfo){
        try {
            Class.forName("org.sqlite.JDBC");
            Connection conn = DriverManager.getConnection("jdbc:sqlite:" + dbFileName);
            conn.setAutoCommit(true);
            String sql = "insert INTO historyfile VALUES (?,?,?,?,?,?) ";
            PreparedStatement stat = conn.prepareStatement(sql);

            stat.setString(1, fileInfo.getFileName());
            stat.setInt(2, fileInfo.getFilePriority());
            stat.setString(3, fileInfo.getUrl());
            stat.setString(4, fileInfo.getCreatedTime().toString("yyyy-MM-dd HH:mm:ss"));
            stat.setString(5, fileInfo.getCategoryName());
            stat.setString(6, fileInfo.getStartDownLoadTime().toString("yyyy-MM-dd HH:mm:ss"));
            stat.executeUpdate();;
            stat.close();
            conn.close();

        }catch (Exception e){
            log.error(e.getMessage());
        }
    }

    /**
     * 查询数据库，判断文件是否已下载
     * @throws Exception
     */
    public synchronized boolean searchLocalFileList(String name,String createTime){
        try {
            Class.forName("org.sqlite.JDBC");
            Connection conn = DriverManager.getConnection("jdbc:sqlite:" + dbFileName);
            conn.setAutoCommit(true);
            Statement stmt = conn.createStatement();

            String sql="select * from currentfile where filename ='"+name+"'";//+" and createTime ='"+createTime+"'";
            ResultSet rs = stmt.executeQuery(sql);

            if (rs.next() == false) {
                stmt.close();
                rs.close();
                conn.close();
                return false;       //该文件未下载
            } else {
                stmt.close();
                rs.close();
                conn.close();
                return true;        //该文件已下载
            }
        }catch (Exception E){
            log.error(E.getMessage());
        }
        return true;
    }
}
